<template>
    <recycle-scroller 
        ref="scroller"
        class="tree-select" 
        size-field="height"
        :style="{'height': height}"
        :item-size="null"
        :min-item-size="0"
        :items="treeNodes"
        :key-field="idKey"
    >
        <template slot-scope="{item, index}">
            <tree-select-node
                :key="item[idKey]"
                :node="item"
                :index="index"
                :label-key="labelKey"
                :item-height="itemHeight"
                :selected="currentNodeId === item[idKey]"
                @expand="handleExpandNode"
                @collapse="handleCollapseNode"
                @click="handleNodeClick"
            >
                <slot slot-scope="scope" v-bind="scope"></slot>
                <template slot="addon" slot-scope="scope">
                    <slot name="addon" v-bind="scope"></slot>
                </template>
            </tree-select-node>
        </template>
    </recycle-scroller>
</template>
<script>
import Vue from 'vue'
import TreeSelectNode from './tree-select-node'
import VueVirtualScroller, { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import TreeSelectStore from './tree-select-store' 

Vue.use(VueVirtualScroller, {
    itemsLimit: Infinity
})

export default {
    name: 'TreeSelect',
    components: {
        TreeSelectNode,
        RecycleScroller
    },
    props: {
        data: {
            type: Array,
            default: () => []
        },
        height: {
            type: String,
            default: '100%'
        },
        itemHeight: {
            type: Number,
            default: 24
        },
        idKey: {
            type: String,
            default: 'id'
        },
        labelKey: {
            type: String,
            default: 'label'
        },
        childrenKey: {
            type: String,
            default: 'children'
        },
        defaultExpandLevel: {
            type: Number
        },
        defaultExpandKeys: {
            type: Array
        },
        filterMethod: {
            type: Function
        },
        current: {
            type: [String, Number]
        }
    },
    watch: {
        data () {
            this.handleDataChange()
        }
    },
    created () {
        this.store = new TreeSelectStore({
            data: this.data,
            idKey: this.idKey,
            itemHeight: this.itemHeight,
            childrenKey: this.childrenKey,
            expandLevel: this.defaultExpandLevel,
            expandKeys: this.defaultExpandKeys,
            current: this.current,
            filterMethod: this.filterMethod
        })
    },
    mounted () {
        this.$watch(() => {
            return this.$refs.scroller.ready
        }, () => {
            this.$nextTick(() => {
                this.scrollTo(this.currentNodeId)
            })
        })
    },
    computed: {
        treeNodes () {
            return this.store.props.nodes
        },
        currentNodeId () {
            return this.store.props.currentId
        }
    },
    methods: {
        handleDataChange () {
            this.store.setData(this.data)
        },
        handleExpandNode ({ node }) {
            this.store.expandNode(node)
        },
        handleCollapseNode ({ node }) {
            this.store.collapseNode(node)
        },
        handleNodeClick ({ node }) {
            this.store.setCurrentNodeId(node[this.idKey])
        },
        filter (keyword) {
            this.store.filter(keyword)
        },
        scrollTo (node) {
            const index = this.store.getNodeIndex(node)
            if (index < 0) {
                return
            }
            this.store.expandNode(this.store.getParentNode(node))
            this.$refs.scroller && this.$refs.scroller.scrollToItem(index)
        }
    }
}
</script>
<style>
.tree-select{
    overflow: auto;
}
</style>